package com.kornero.auto.controller;

import com.kornero.auto.util.Threads;
import com.kornero.auto.view.groups.IAutoUpdateGroup;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class AutoUpdateController extends AbstractController<IAutoUpdateGroup> {

    private static final Logger logger = LoggerFactory.getLogger(AutoUpdateController.class);

    private final ScheduledExecutorService autoUpdateThreadPool = Executors.newSingleThreadScheduledExecutor();

    private final Runnable task;

    private volatile ScheduledFuture autoUpdateFuture;

    public AutoUpdateController(final Runnable task, final IAutoUpdateGroup autoUpdate) {
        super(autoUpdate);
        this.task = new UpdateWithNotification(task);
        this.bind();
    }

    private void bind() {
        this.getView().addStartListener(new Listener() {
            @Override
            public void handleEvent(Event event) {
                startListenerAction();
            }
        });
        this.getView().addStopListener(new Listener() {
            @Override
            public void handleEvent(Event event) {
                stopListenerAction();
            }
        });
    }

    private void startListenerAction() {
        final ScheduledFuture autoUpdateFuture =
                autoUpdateThreadPool.scheduleWithFixedDelay(task, 1, 1, TimeUnit.SECONDS);
        setAutoUpdateFuture(autoUpdateFuture);
    }

    private void stopListenerAction() {
        autoUpdateFuture.cancel(true);
        getView().setStatus("Stopped.");
    }

    private void setAutoUpdateFuture(final ScheduledFuture autoUpdateFuture) {
        this.autoUpdateFuture = autoUpdateFuture;
    }

    @Override
    public void stop() {
        if (null != autoUpdateFuture) {
            autoUpdateFuture.cancel(true);
        }
        autoUpdateThreadPool.shutdownNow();
    }

    private class UpdateWithNotification implements Runnable {

        private final Runnable update;

        private UpdateWithNotification(final Runnable update) {
            this.update = update;
        }

        @Override
        public void run() {
            getView().setStatus("Updating now...");
            update.run();

            final Thread me = Thread.currentThread();
            for (long remaining = getView().getTimeout(); remaining >= 0; remaining--) {
                if (me.isInterrupted()) {
                    getView().setStatus("Stopped.");
                    return;
                }
                getView().setStatus("Remaining: " + remaining + " sec.");
                Threads.sleep(1000);
            }
        }
    }
}
